package com.sxhuayuan.parking.utils;

import org.apache.commons.codec.binary.Hex;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
 * DES加密、解密工具类<br/>
 * 算法/工作模式/填充模式: DES/CBC/PKCS5Padding<br/>
 * 输出方式：HEX
 * @author helong
 * @create 2019-08-28 9:12
 */
public class DESUtils {
	private static final String TRANSFORMATION = "DES/CBC/PKCS5Padding";
	private static final String ENCRYPTION_MODE = "DES";
	/**
	 *
	 * @param data 要加密的字符串
	 * @param key 私钥:
	 *            AES固定格式为128/192/256 bits.即:16/24/32bytes。
	 *            DES固定格式为128bits，即8bytes。
	 *
	 * @param iv 初始化向量参数
	 *              AES 为16bytes.
	 *              DES 为8bytes.
	 * @return
	 * @throws Exception
	 */
	public static String encrypt(String data, String key, String iv) throws Exception
	{
		try
		{
			/**
			 *
			 * AES和DES 一共有4种工作模式:
			 *     1.电子密码本模式(ECB) -- 缺点是相同的明文加密成相同的密文，明文的规律带到密文。
			 *     2.加密分组链接模式(CBC)
			 *     3.加密反馈模式(CFB)
			 *     4.输出反馈模式(OFB)四种模式
			 *
			 * PKCS5Padding: 填充方式
			 *
			 * 加密方式/工作模式/填充方式
			 * DES/CBC/PKCS5Padding
			 */
			Cipher cipher = Cipher.getInstance(TRANSFORMATION);
			byte[] dataBytes = data.getBytes();

			//两个参数，第一个为私钥字节数组， 第二个为加密方式 AES或者DES
			SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), ENCRYPTION_MODE);
			IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());

			/**
			 * 初始化，此方法可以采用三种方式，按服务器要求来添加。
			 * (1)无第三个参数 --> iv
			 * (2)第三个参数为SecureRandom random = new SecureRandom();中random对象，随机数。(AES不可采用这种方法)
			 * (3)采用此代码中的IVParameterSpec --> 指定好了的
			 *
			 * 解密使用 DECRYPT_MODE 方式
			 */
			cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
			byte[] encrypted = cipher.doFinal(dataBytes);
			return Hex.encodeHexString(encrypted);
		}
		catch (Exception e)
		{
			e.printStackTrace();
			return null;
		}
	}

	public static String decrypt(String dataEncode, String key, String iv) throws Exception
	{
		try
		{
			//先用Hex解码
			byte[] encrypted1 = Hex.decodeHex(dataEncode.toCharArray());

			Cipher cipher = Cipher.getInstance(TRANSFORMATION);
			SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), ENCRYPTION_MODE);
			IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());

			// 解密使用 DECRYPT_MODE 方式
			cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);

			byte[] original = cipher.doFinal(encrypted1);
			return new String(original);
		}
		catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	public static void main(String[] args) throws Exception
	{
		String s = "354651148486848";
		String data = "6464";
		String key = "12345678";
		String iv = "abcdefgh";

		String en = encrypt(data, key, iv);
		String de = decrypt(en, key, iv);

		System.out.println("明文: " + data);
		System.out.println("加密: " + en);
		System.out.println("解密: " + de);
	}
}
